#include "wet.h"
#include <libpq-fe.h>
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
#include <math.h>
#include <stdio.h>


#define MAX_INT_AS_STRING_LENGTH 11

PGconn *conn = NULL;


/*
 * Returns the total(sum) length of multiple strings
 */
static size_t strlen_multi(int num_args, ...)
{
	char *val;
        va_list lptr;
        int len = 0, i = 0; 
         
        va_start(lptr, num_args);
        while (i++ < num_args)
	{
		val = va_arg(lptr, char*);
                len += strlen(val);
       	}
        va_end(lptr);
	return len;
} 

static PGresult *do_query(const char *qp, ...)
{
	char *val;	
	char *query;
	char *tmp;
	va_list lptr;
	PGresult *res;	
	int len = strlen(qp);

	va_start(lptr, qp);
	while ((val = va_arg(lptr, char*)) != NULL)
	{
		printf(val);
		len += strlen(val);
	}
	va_end(lptr);

	query = malloc(len+1);
	tmp = malloc(len+1);
	printf("%d\n", len+1);
	strcpy(tmp, qp);
	sprintf(tmp, qp, "adam");
	printf("%s", tmp);
	va_start(lptr, qp);
	printf("%s", qp);
	while ((val = va_arg(lptr, char*)) != NULL)
	{
		printf(tmp);
		sprintf(query, tmp, val);
		strcpy(tmp, query);
	}
	va_end(lptr);
	printf("%s\n", query);
	printf("%s\n", tmp);
	res = PQexec(conn, query);
	free(query);
	free(tmp);
	return res;
}

static void exit_nicely(PGconn *conn)
{
    PQfinish(conn);
    exit(1);
}

void* addQuestion(const char* question, const char* username, const char* date)
{
	PGresult *res = NULL;
	char *bq = NULL, *q = NULL;
	
	// bulding the query that checks if the user already
	// asked a questions in the given date
	bq = "SELECT qid FROM questions WHERE asker='%s' AND date='%s'";
	q = malloc(strlen_multi(2, question, username) + strlen(bq) + 1);	
	sprintf(q, bq, username, date);
	res = PQexec(conn, q);
	free(q);
	
	if (PQntuples(res)) // questions already asked by the user in date
	{
		printf(EXISTING_RECORD);
		PQclear(res);
		return NULL;		
	}
	PQclear(res);
	
	// build the INSERT DMS
	bq = "INSERT INTO questions VALUES ((SELECT MAX(qid) + 1 FROM questions), '%s', '%s', '%s') RETURNING qid";
        q = malloc(strlen_multi(3, question, username, date) + strlen(bq) + 1);
        sprintf(q, bq, question, username, date);
	res = PQexec(conn, q);
        free(q);

	printf(QUESTIONS_TABLE_HEADER);	
	printf(QUESTIONS_TABLE_LINE, PQgetvalue(res, 0, 0), question, username, date, "");

	return NULL;
}

void* editQuestion(const int qid, const char* question)
{
	PGresult *res = NULL;
	char *bq = NULL, *q = NULL, *tags = NULL, *username = NULL, *date = NULL, s_qid[MAX_INT_AS_STRING_LENGTH + 1];
	int num_rows = 0, i = 0, tags_length = 0;
	
	// build the UPDATE DMS
	bq = "UPDATE questions SET question='%s' WHERE qid=%d RETURNING qid, question, asker, date";
	q = malloc(strlen(question) + strlen(bq) + MAX_INT_AS_STRING_LENGTH + 1);
	sprintf(q, bq, question, qid);
	res = PQexec(conn, q);

	if (!PQntuples(res)) // question with qid not found
	{
		printf(ILL_PARAMS);
		PQclear(res);
		return NULL;
	}

	// saving username and date returned from update
	username = malloc(PQgetlength(res, 0, 2) + 1);
	date = malloc(PQgetlength(res, 0, 3) + 1);
	strcpy(username, PQgetvalue(res, 0, 2));
	strcpy(date, PQgetvalue(res, 0, 3));	
	PQclear(res);	
	bq = "SELECT tag FROM tags WHERE qid=%d";
	sprintf(q, bq, qid);
	res = PQexec(conn, q);
	free(q);
	
	// in case the question has tags, make a string out of them
	if (num_rows = PQntuples(res))
	{
		for (i = 0; i < num_rows; ++i)
			tags_length += PQgetlength(res, i, 0);
		
		tags = malloc(tags_length + num_rows + 1);
		tags[0] = '\0';

		for (i = 0; i < num_rows; ++i)
		{
			strncat(tags, PQgetvalue(res, i, 0), PQgetlength(res, i, 0));
			strcat(tags, " ");
		}
		tags[strlen(tags) - 1] = '\0';
	}
	else
		tags = "";

	PQclear(res);
	sprintf(s_qid, "%d", qid);
	printf(QUESTIONS_TABLE_HEADER);
	printf(QUESTIONS_TABLE_LINE, s_qid, question, username, date, tags);
	if (strlen(tags)) // free tags if not empty (means we allocated)
		free(tags);
	return NULL;
}

void* deleteQuestion(const int qid)
{
	PGresult *res = NULL;
	char *bq = NULL, *q = NULL;
	
	// build the delete DMS
	bq = "DELETE FROM questions WHERE qid=%d";
	q = malloc(strlen(bq) + MAX_INT_AS_STRING_LENGTH + 1);
	sprintf(q, bq, qid);
	res = PQexec(conn, q);

	PQclear(res);
	
	// if no question was deleted it means it wasn't there
	// so returning ILL_PARAMS 
	if (!atoi(PQcmdTuples(res)))
	{
		printf(ILL_PARAMS);
		return NULL;		
	}
	
	// build the DMS that deletes corresponding tags
	bq = "DELETE FROM tags WHERE qid=%d";
	sprintf(q, bq, qid);
	res = PQexec(conn, q);
	PQclear(res);
	
	free(q);
	
	return NULL;
}

void* addTag(const int qid, const char* tag)
{
	return NULL;
}

void* removeTag(const int qid, const char* tag)
{
	return NULL;
}

void* printTags(const int qid)
{
	return NULL;
}

void* addAnswer(const int qid, const char* answer)
{
	return NULL;
}

void* editAnswer(const int aid, const char* answer)
{
	return NULL;
}

void* deleteAnswer(const int aid)
{
	return NULL;
}

void* approveAnswer(const int aid)
{
	return NULL;
}

void* findAnswers(const int qid)
{
	return NULL;
}

void* searchByTag(const char* tag)
{
	return NULL;
}

void* findRelatedTags(const char* tag)
{
	return NULL;
}

void* findRelatedQuestions(const int qid)
{
	return NULL;
}

void* printStatistics()
{
	return NULL;
}

void* interestingTags()
{
	return NULL;
}

void* bestAnswersForTag(const char* tag)
{
	return NULL;
}

void* deleteRedundantAnswers()
{
	return NULL;
}


int main(void)
{
	char connect_param[80];
	sprintf(connect_param, "host=pgsql.cs.technion.ac.il dbname=%s user=%s password=%s", USERNAME, USERNAME, PASSWORD);
	conn = PQconnectdb(connect_param);
	if (!conn || PQstatus(conn) == CONNECTION_BAD)
	{
		fprintf(stdout, "Connection to server failed %s\n", PQerrorMessage(conn));
		PQfinish(conn);
		return 1;
	}
	parseInput();
	PQfinish(conn);	
	return 0;
}
